﻿using Microsoft.Extensions.Configuration;

namespace Luka.Log;

/// <summary>
/// 配置文件扩展
/// </summary>
internal static class ConfigurationExtension
{
    /// <summary>
    /// 自动合并配置文件
    /// </summary>
    public static IConfigurationBuilder MergeConfiguration(this IConfigurationBuilder configuration)
    {
        // 获取当前应用程序域的基本目录
        var executeDirectory = AppDomain.CurrentDomain.BaseDirectory;
        // 设置配置文件的基本路径
        configuration.SetBasePath(executeDirectory);
        // 添加appsettings.json配置文件
        configuration.AddJsonFile("appsettings.json", true, true);
        // 添加appsettings.{EnvironmentName}.json配置文件
        configuration.AddJsonFile($"appsettings.{InternalApp.EnvironmentName}.json", true, true);
        // 构建配置
        var config = configuration.Build();
        // 获取配置目录
        var dirs = config.GetSection("ConfigurationScanDirectories").Get<string[]>() ?? Array.Empty<string>();
        // 获取所有json文件
        var jsonFiles = new[] { executeDirectory }
                            .Concat(dirs.Where(dir => Directory.Exists(dir)))
                            .SelectMany(u => Directory.GetFiles(u, "*.json", SearchOption.TopDirectoryOnly))
                            .ToList();
        // 如果没有json文件，则返回
        if (!jsonFiles.Any()) return configuration;

        // 获取忽略的配置文件
        var ignoreFiles = config.GetSection("IgnoreConfigurationFiles").Get<string[]>() ?? Array.Empty<string>();
        // 将配置文件按组分组
        var filesGroups = SplitConfigFileNameToGroups(jsonFiles.Where(it => !ignoreFiles.Contains(it.Split('.').FirstOrDefault()))).ToList();
        // 遍历每个组
        foreach (var group in filesGroups)
        {
            // 获取限制的文件名
            var limitFileNames = new[] { $"{group.Key}.json", $"{group.Key}.{InternalApp.EnvironmentName}.json" };
            // 获取符合条件的文件
            var files = group
                .Where(u => limitFileNames.Contains(Path.GetFileName(u), StringComparer.OrdinalIgnoreCase))
                .OrderBy(u => Path.GetFileName(u).Length)
                .ToList();

            // 遍历每个文件
            foreach (var jsonFile in files)
            {
                // 添加json文件
                configuration.AddJsonFile(jsonFile, optional: true, reloadOnChange: true);
            }
        }
        return configuration;
    }

    /// <summary>
    /// 对配置文件名进行分组
    /// </summary>
    private static IEnumerable<IGrouping<string, string>> SplitConfigFileNameToGroups(IEnumerable<string> configFiles)
    {
        // 根据Function函数对configFiles进行分组
        return configFiles.GroupBy(Function);
        // 定义Function函数，用于对文件名进行分组
        static string Function(string file)
        {
            // 获取文件名，并按'.'进行分割
            var fileNameParts = Path.GetFileName(file).Split('.', StringSplitOptions.RemoveEmptyEntries);
            // 如果分割后的数组长度为2，则返回第一个元素
            if (fileNameParts.Length == 2) return fileNameParts[0];

            // 否则返回除了最后两个元素之外的所有元素，用'.'连接
            return string.Join('.', fileNameParts.Take(fileNameParts.Length - 2));
        }
    }
}